package com.eva.framework.common.servlet.rewrite;

import com.eva.framework.common.servlet.ServletProperties;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Component;

import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 重写请求和响应流
 * - 拷贝请求流和响应流，以实现多次流读取
 * - 可通过app.servlet.rewrite.exclude-path-patterns排除掉不需要拷贝的请求
 */
@Component
@WebFilter(urlPatterns = "/*", filterName = "servletRewriteFilter")
public class ServletRewriteFilter implements Filter {

    @Resource
    private ServletProperties servletProperties;

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
        // 排除路径正则处理（无需拷贝请求流和响应流副本）
        String uri = httpServletRequest.getRequestURI().replace(httpServletRequest.getContextPath(), "");
        for (String pattern : servletProperties.getRewrite().getExcludePathPatterns()) {
            if (uri.matches(pattern.trim())) {
                filterChain.doFilter(servletRequest, servletResponse);
                return;
            }
        }
        // 拷贝请求流副本，由ServletDuplicateRequestWrapper存储副本
        ServletRequest requestWrapper = servletRequest;
        if (!(requestWrapper instanceof ServletDuplicateRequestWrapper)) {
            requestWrapper = new ServletDuplicateRequestWrapper(httpServletRequest);
        }
        // 拷贝响应流副本，由ServletDuplicateResponseWrapper存储副本
        ServletResponse responseWrapper = servletResponse;
        if (!(servletResponse instanceof ServletDuplicateResponseWrapper)) {
            responseWrapper = new ServletDuplicateResponseWrapper(httpServletResponse);
        }
        filterChain.doFilter(requestWrapper, responseWrapper);
    }
}
